<h2>概述</h2>
<p>最近1个星期，读了《DevOps实践指南》，非常有感触。我从09年开始实践敏捷，差不多10年了，从最初的RUP，到XP，再到Scrum，我已经让团队做到了3-4周发布一次，但是Devops刷新了我的观点，它居然能够做到随时发布，而且以每日多次发布为荣，还能保证质量、多版本同时在线以及问题的实时反馈，这就非常厉害了，所以我认为我的理念应该再度进化，我和我的团队应该去实践DevOps，我认为这就是当下最好的知识，我们每个人都应该学习。
</p>
<h2>笔记</h2>
<h3>第一部分 三步工作法</h3>
<ol>
    <li>任何公司都是科技公司，无论是处在哪个行业，不论他们有没有意识到。银行也只是有金融执照的IT公司而已，没有这么想的公司都已经开始落后了。</li>
    <li>应用了DevOps的公司在以下几个方面表现得比未使用的要好。
        <ul>
            <li>吞吐量指标</li>
            <li>代码和变更部署次数（频繁30倍）</li>
            <li>代码和变更部署的前置时间（快200倍）</li>
            <li>可靠性指标</li>
            <li>生产环境部署（变更成功率高60倍）</li>
            <li>平均服务恢复时间（快168倍）</li>
            <li>组织性能指标</li>
            <li>生产力、市场份额以及营业目标（大约2倍以上）</li>
            <li>市值增长（3年内高出50%）</li>
        </ul>
    </li>
    <li>DevOps的三步工作法：流动、反馈以及持续学习与实验。
        <ul>
            <li>流动：加速了软件交付的流程</li>
            <li>反馈：建设出更可靠的工作体系</li>
            <li>持续学习与实验：打造高度信任的文化和一种科学的工作方式，并将改进和创新作为日常工作的一部分</li>
        </ul>
    </li>
    <li>DevOps是博采众家之长，其中包括：
        <ul>
            <li>精益运动，其精髓是，坚信前置时间（生产从原料到成品时间）是提升质量、客户满意度和员工幸福感的最佳度量指标；小批量的交付是缩短前置时间的关键因素</li>
            <li>敏捷宣言，精髓强调了有价值的交付胜于一切，与客户保持沟通与反馈胜于冗繁细致的文档</li>
            <li>丰田套路，其精髓为看板思想。</li>
        </ul>
    </li>
    <li>返工指标 %C/A<br>
        返工指标是完成时间和精确的总花费时间的百分比（%C/A）。<br>
        举个例子，开发系统完成时间是8小时，但是修改BUG等一系列的时间，最后到稳定，时间又增加了8小时，那么总时间就是16小时，返工指标就是8 / 16 = 50%，这说明这个东西完成得并不好。</li>
    <li>看板必须要控制“doing”的数量<br>
        如果“doing”的数量增多，那么会加大复杂度，不够快速，“停止开始，开始结束”。DevOps推荐测试工作的数量上限是3个，3个测试用例做完了，再继续做3个。</li>
    <li>要快必须是松耦合的架构，自动化的测试环境，自动化的部署环境</li>
    <li>组织的几种类型
        <ul>
            <li>病态型<br>
                隐瞒信息、消灭信使、逃避责任、阻碍团队的互动、隐瞒事故、压制新想法</li>
            <li>官僚型<br>
                忽略信息、不重视信使、各自担责、容忍团队的互动、公道和宽容、认为新想法会造成麻烦和风险</li>
            <li>生机型<br>
                积极探索信息、训练信使、共同担责、鼓励团队结盟、调查事故根因，接纳新想法</li>
        </ul>
    </li>
    <li>比日常工作更重要的是对日常工作的改进。</li>
    <li>局部发现转化为全局优化<br>
        一旦在局部范围获得了成果，就应当把它分享给组织里的其他人，让更多人从中受益。建立全局知识库。</li>
</ol>
<h3>第二部分 从何处开始</h3>
<ol>
    <li>
        <p>绿地项目和棕地项目<br>
            绿地是指全新开始，棕地是指在已有的项目上开始。借鉴的是工业时期的思想，绿地是天然的地面，没有被人工使用过，而棕地因为人工的使用而导致了地面污染，成了棕色。</p>
    </li>
    <li>
        <p>记录型和交互型系统。<br>
            记录型系统强调的是“做得正确”，例如一些需要符合监管、审计等项目。<br>
            交互型系统强调的是“做得快速”，例如电子商务、社交和娱乐项目。<br>
            而DevOps是可以兼顾这两个系统的。</p>
    </li>
    <li>
        <p>一个组织的转型最好是从最能接受的那群先驱者开始，然后逐步让那些保守主义者接受。当然如果有最高层支持，那么可以直接一竿子插到底，彻底转型。</p>
    </li>
    <li>
        <p>为客户创造价值的团队成员</p>
        <ul>
            <li>产品负责人：业务方的代言人，定义系统需要实现的功能。</li>
            <li>开发团队：负责开发系统功能。</li>
            <li>QA团队：给开发团队提供反馈，并确保系统功能复合需求。</li>
            <li>运维团队：负责维护生产环境，并确保系统能够良好的运行。</li>
            <li>信息安全团队：负责系统和数据的安全。</li>
            <li>发布经理：负责管理和协调生产环境部署以及发布流程。</li>
            <li>技术主管或价值流经理：负责“从始至终地保障价值流的产出满足或超出客户（和组织）的期望”。</li>
        </ul>
    </li>
    <li>
        <p>为非功能性需求留出20%的开发时间，用于重构、调优等，来减少技术债务。这些都是用户不可见但是又十分重要的隐性价值。</p>
    </li>
    <li>
        <p>组织原型</p>
        <ul>
            <li>职能型，注重提高专业技能、优化分工或降低成本。运维部门通常采用这种组织类型，用职能划分不同的小组。</li>
        </ul>
        <p>职能型会延长交付时间，而且不同职能的人不知道其他职能的工作价值， 缺乏创造性。</p>
        <ul>
            <li>矩阵型，结合了职能和市场型组织的特点。通常较为复杂，一名员工可能会有多个不同职能的负责人需要汇报，有时候会起到降低效率的作用。</li>
            <li>市场型，注重快速响应客户需求。往往较为扁平化，由多个跨职能的部门组成，例如营销和技术，所以也存在一定职能的冗余现象。</li>
        </ul>
    </li>
    <li>
        <p>人才分为I型、T型、E型</p>
        <ul>
            <li>I型，专家型，在某个领域精通，其他领域经验和技能很少，很快遇到瓶颈，对下游的浪费和影响不敏感。抵制灵活或可变的计划。</li>
            <li>T型，通才型，精通某个领域，拥有多个领域的经验和技能，能突破瓶颈，对下游的浪费和影响敏感，帮助制定灵活和可变的计划。</li>
            <li>E型，精通某几个领域，有多个领域的实践经验，执行能力强，能持续创新，潜力无限。</li>
        </ul>
    </li>
    <li>
        <p>创建松耦合架构，提供生产力和安全性，保持团队小规模。<br>
            一个团队有“两个比萨”的说法，指团队人数不超过吃掉“两个比萨”的人数，大概是5-10人。好处有4个，</p>
        <ul>
            <li>小团队对系统有清晰、相同的理解。</li>
            <li>限制产品或服务的增长率。</li>
            <li>分散权力并实现自主。</li>
            <li>小团队更扁平化，每个人都获得领导经验。</li>
        </ul>
    </li>
    <li>
        <p>将运维融入日常开发工作</p>
        <ul>
            <li>构建自服务能力，帮助开发人员提高生产力；</li>
            <li>将运维工程师融入服务团队；</li>
            <li>如果运维工程师紧张，则可以采用运维联络人模式。</li>
        </ul>
    </li>
    <li>
        <p>如果没有这些自服务运维平台，云环境只是昂贵的主机托管服务2.0</p>
    </li>
</ol>
<h3>第三部分 流动的技术实践</h3>
<ol>
    <li>应用统一的源码仓库<br>
        开发环境、测试环境、生产环境应该都是统一的仓库，而不是各有各的仓库，在源码开发上就要考虑不同环境的情况，包括各个环境的配置、容器、脚本等等。（例如SpringBoot的Profile）。</li>
    <li>实现快速可靠的自动化测试<br>
        不接受低测试覆盖率的代码变更。搭建自动化测试流程，保证代码的搞测试覆盖率，编写测试规范和指南，坚持团队内外部人员执行。</li>
    <li>对代码和环境做持续构建、测试和集成
        <ul>
            <li>在任何时候，构建和测试流程都能够运行，无论工程师的个人习惯如何。</li>
            <li>独立的构建和测试流程确保工程师能够理解构建、打包、运行和测试代码所需的全部依赖项（不能出现在我的电脑上行，在服务器上就不行的情况。）</li>
            <li>将应用的可执行文件和配置打包，并可以在环境中重复安装（如RPM、yum、npm，Java的JAR，Ruby的Gem等）</li>
            <li>将应用打包到可部署的容器中（如Docker、Rkt、LXD和AMI）</li>
            <li>以一致、可重复的方式进行类生产环境的配置（如关闭调试标识、移除编译器等）<br>
                每次代码变更之后，部署流水线都应该确认代码已经成功的集成到了类生产环境中。</li>
        </ul>
    </li>
    <li>自动化测试从快到慢分为如下几类。
        <ul>
            <li>单元测试：独立测试每个方法、类或函数。</li>
            <li>验收测试：整体测试应用，确保各个功能模块按照正常设计工作，且没有引入回归错误。</li>
            <li>集成测试：保证应用能与生产环境中的其他应用和服务正确的交互。<br>
                如果编写单元测试较为困难，则说明软件模块设计上过于耦合，边界不够明显。需要重新设计成更加松散的架构。</li>
        </ul>
    </li>
    <li>在部署流水线失败时拉下安灯绳<br>
        在未解决问题之前，任何更新都不能够被接受。安灯绳也可以变更为多种有趣的形式，甚至可以和物联网结合起来，例如构建失败时敲响闹钟、打开黑胶唱片等提示方式。<br>
        为何要弄一个安灯绳？
        <ul>
            <li>有人提交的代码造成构建或者自动化测试失败，但是没人修复</li>
            <li>其他人在已经失败的构建版本上又提交了变更。造成错误累计，使得错误修正更加复杂。</li>
            <li>新的测试用例无法构建，因为现有的测试用例未通过，而且也不能将错就错。</li>
        </ul>
    </li>
    <li>如果没有自动化测试，持续集成只能产生一大堆没有经过编译而且不能正确运行的垃圾。</li>
    <li>分支策略可以分为两类。
        <ul>
            <li>提高个人生产力，每人一个分支，但是合并时会带来困难。</li>
            <li>提高团队生产力，共同工作一个分支，但是任何一次提交可能破坏项目的整体情况。</li>
        </ul>
    </li>
    <li>将部署与发布解耦
        <ul>
            <li>部署是指在特定的环境中安装制定版本的软件。</li>
            <li>发布是指把一个或一组特性提供给所有客户或者一部分客户。</li>
        </ul>
    </li>
</ol>
<p>8.1 基于环境的发布模式<br>
    在两个或者多个环境中部署系统，但是实际只有一个环境处理真实的客户流量（例如通过负载均衡进行处理）。当新的版本完成之后，再切换到新版本上，这种模式包括蓝绿部署、金丝雀发布和集群免疫系统。</p>
<p>这个发布模式的难度在于数据库的变更，一般有两个玩法：<br>
    * 创建两个数据库，发布期间，另外一个库变成只读模式，这样就不会有数据更新。（个人感悟，这个操作模式其实较为复杂，不好处理）<br>
    * 采用扩展收缩模式，增量处理数据库，然后再部署成功后利用收缩删除不再使用的数据表。</p>
<p>8.2 基于应用的发布模式<br>
    对应用进行修改，通过细微的配置变更，选择性的开放应用。（个人感悟：魔兽世界就是一个很好的例子，上线新版本的时候用户就开始下载新的版本所有文件，当时间一到，用户不用再次进行更新即可使用新的内容）。这个技术就是所谓的黑启动技术。
</p>
<ol>
    <li>
        <p>技术的架构应该采用的是能提高生产力、可测试性和安全性的架构<br>
            单体架构是不行的（个人感悟：也看具体的项目大小，单人小项目单体架构是可行的），微服务架构是可取的，不同模块之间通过定义清晰的版本化API进行松耦合。</p>
    </li>
    <li>
        <p>绞杀者应用<br>
            是指通过全新系统去替换旧系统的应用，首先封装旧系统为API，然后使用新架构逐步替换掉旧的应用，最后摒弃掉老的系统。</p>
    </li>
</ol>
<h3>第四部分 反馈的技术实践</h3>
<ol>
    <li>集中式监控架构</li>
</ol>
<ul>
    <li><strong>在业务逻辑、应用程序和环境层收集数据</strong>：最好是将所有日志都归集到一个公共的目录下，便于集中、轮换和清理。设立好收集指标，能更好地了解系统的状态，使用collectd、Ganglia等工具采集状态指标，如CPU、内存、磁盘或者网络等等，以及其他工具采集性能指标。
    </li>
    <li><strong>负责存储和转发事件和指标的事件路由器</strong>：此功能支持监控可视化、趋势分析、告警、异常检测等。这些工具可以是Sensu、Nagios、Zabbix、LogsStash、Splunk、Sumo
        Logic、Datadog和Riemann。</li>
</ul>
<ol>
    <li>建立生产环境的应用程序日志遥测<br>
        有了集中式监控架构，就可以对生产环境的应用程序日志进行遥测了。我们应该监测每个功能，保证他们能够如期运转。</li>
</ol>
<p>日志的级别划分：</p>
<ul>
    <li>调试级别：生产运行中禁用，但是在有错误出现时，开启进行调试</li>
    <li>信息级别：包括用户出发的或系统特定的操作（例如，“开始信用卡交易”）</li>
    <li>警告级别：告诉我们可能存在风险（例如，查询数据库花费了一个较长的时间）</li>
    <li>错误级别：告诉我们系统出了问题（例如，API调用失败，远程系统无法调用，内部出错等等）</li>
    <li>致命级别：发生了中段情况（例如，无法绑定访问端口，套接字无法打开）</li>
</ul>
<p>日志应该记录哪些？</p>
<ul>
    <li>认证/授权的结果（包括退出）</li>
    <li>系统和数据的访问</li>
    <li>系统和应用程序的变更（特别是特权变更）</li>
    <li>数据的变更，例如增加、修改或删除数据</li>
    <li>无效输入（可能的恶意注入、威胁等）</li>
    <li>资源（内存、磁盘、CPU、网络或其他任何具有硬/软限制的资源）</li>
    <li>健康度和可用性</li>
    <li>启动和关闭</li>
    <li>故障和错误</li>
    <li>断路器跳闸</li>
    <li>延迟</li>
    <li>备份成功/失败</li>
</ul>
<p>这些日志应该进行分类和分级，例如分功能属性（性能、安全）和功能属性（搜索、排行）</p>
<p>我们应该遥测哪些？</p>
<ul>
    <li>业务级别：包括交易订单的数量、产生的营业额、用户注册数、流失率、A/B测试的结果等。</li>
    <li>应用程序级别：包括事务处理时间、用户响应时间、应用程序故障等。</li>
    <li>基础架构级别（如数据库、OS、网络、存储）：包括Web服务器的吞吐量、CPU负载、磁盘使用率等</li>
    <li>客户端软件级别（如客户端浏览器上的JS、移动应用程序）：包括应用程序的崩溃和出错、用户端的事务处理时间等。</li>
    <li>部署流水线级别：包括流水线的状态（如各种测试套件的红色或绿色状态）、变更部署的前置时间、部署频率、测试环境上线状态和环境状态</li>
</ul>
<p>将这些遥测的内容呈现在<strong>信息辐射器</strong>上，可以使得项目相关人员了解当前整体情况，使得价值流水线相关人员直面问题。</p>
<ol>
    <li>分析遥测数据以更好的预测故障和实现目标<br>
        <strong>均值和标准差</strong>是一个非常简单和强大的统计学工具，能够非常有效的度量我们的故障，例如我们每天未经授权进行登录的数量大致在50个（均值），而今天突然出现了150，甚至是300个，或者是突然少于了20个（标准差出现），那么一定是出现了问题，需要及时进行处理。DevOps定义了三个级别来界定标准差，第一、第二和第三分别包含68%、95%和99.7%的数据。他们分别对称分布在均值的左右两边（正态分布）。这样处理还有个好处就是不必设置静态的阈值，而是采用均值和标准差就能动态的设置阈值，进行遥测和反馈。
    </li>
</ol>
<p>当然，也存在呈现非正太分布的情况，例如下载量的监控，有可能出现高低都超出了均值3个标准差的情况，可以采用<strong>平滑</strong>的统计技术，它对于时间序列数据特别适用，这意味着每个数据点都有一个时间戳（例如，下载、已完成的事务处理事件等）。平滑技术通常涉及使用<strong>移动平均数</strong>（滚动平均数），它利用每个点与滑动窗口中的所有其他数据的平均值，来交换数据。这样做有助于抑制短期波动，突出长期趋势和周期。
</p>
<p>还有一些其他的统计技术可以用于数据的遥测监控和预测处理，例如傅里叶变换和Kolmogorov-Smirnov检验，前者广泛用于图像处理，后者经常用于分析周期性/季节性度量数据的相似性或差异性。</p>
<ol>
    <li>应用反馈实现安全部署<br>
        在部署的时候应该严格监控遥测的指标，如果指标出现了异常，那么就需要及时的反馈，是立刻发布补丁还是回退版本等操作。</li>
</ol>
<p>开发和运维应该同时承担值班工作，而不是只有运维，这样可以更快的解决问题，而不是运维拿到问题的日志之后，等待开发人员介入。</p>
<p>建立<strong>服务回传机制</strong>。当生产环境中的一个服务变得非常脆弱时，运维部门能把支持这个服务的责任交回给开发部门。责任的转换会督促开发人员更加重视开发的健壮性，减少运维的压力，也是运维和开发之间相互协作、相互尊重的最佳体现。
</p>
<ol>
    <li>
        <p>将A/B测试和假设驱动开发融入日常工作<br>
            A/B测试最早用于直效营销（两大营销手段之一，另外一个是品牌营销或大众营销），直效会投放很多资源会消耗大量成本，而采用A/B测试之后会有效降低成本，并提高准确率。</p>
        <ul>
            <li>在功能测试中集成A/B测试：好处是能够快速辨别功能对于结果之间的影响。</li>
            <li>在发布中集成A/B测试： 通过使用类似特性开关、特性API等方式支撑A/B测试。</li>
            <li>在功能规划中集成A/B测试：在功能规划之初就应该规划A/B测试，同一个功能可能有两个或者多个方式，功能开发中通过特性开关去支撑这两个方式。</li>
        </ul>
    </li>
    <li>
        <p>建立协作和评审流程以提升工作质量<br>
            6.1 GitHub Flow</p>
        <ul>
            <li>工程师为了开发一项新的功能需求，要基于主干建立一个命名清晰的分支（例如，new-oauth2-scopes）</li>
            <li>工程师提交代码到本地分支，并定期将工作成果推送到远程服务器的同名分支上</li>
            <li>当他们需要反馈和帮助时，或者准备将这个分支的代码合并到主干时，就会提交一个Pull Request</li>
            <li>在他们获得期望的评审并通过必要的审核之后，就可以将代码合并到主干了</li>
            <li>一旦将代码合并到主干，工程师就可以将其部署到生产环境了</li>
        </ul>
    </li>
</ol>
<p>6.2 同行变更评审优于普通的变更评审<br>
    在开发中，这样的行为叫代码评审。这个行为同样适用于测试工程师和运维工程师，通过同行不同的视角来审查自己的工作，能够更快更好的发现错误。不仅仅是提升了代码质量，还能相互学习。</p>
<h3>第五部分 持续学习与实验的技术实践</h3>
<ol>
    <li>
        <p><strong>将学习融入日常工作</strong><br>
            建立公正和学习的文化。两个有效的实践有助于建立公正和学习的文化</p>
        <ul>
            <li>不指责的事后分析</li>
            <li>在生产环境中引入受控的人为故障，用于创造机会针对复杂系统中不可避免的问题进行练习（例如AWS的捣蛋猴程序，会随机删除某几个运行中的服务）<br>
                要尽可能广泛地公开事后分析会议结果。对事故要降低容忍度。鼓励评估风险。<br>
                创建故障演练日，用于演练特别的灾难恢复。加大整个系统的抗压能力。</li>
        </ul>
    </li>
    <li>
        <p>将局部经验转化为全局改进<br>
            使用聊天机器人自动积累组织知识。例如GitHub的ChatOps，以及Hubot软件，他们能够帮助建立工作透明度和创建工作文档。还有其他很多优点（相比较于自动化脚本）：</p>
        <ul>
            <li>每个人都能看到发生的一切</li>
            <li>新来的工程师也可以看到团队的日常工作以及执行方式</li>
            <li>看到其他人相互帮助时，人们也会更倾向于寻求帮助</li>
            <li>建立起组织学习，知识得到快速积累<br>
                GitHub的Hubot能出发很多自动化工具，包括Puppet、Capistrano、Jenkins、Resque和GraphMe。</li>
        </ul>
    </li>
</ol>
<p>每个在聊天室的人都可以直接询问机器人，例如：“如何进行部署？”，机器人就会根据自己的知识库来回答你答案。</p>
<p>与把文档写到word中，并存入文件服务器相比，甚至与wiki知识库相比，聊天机器人具有更高效、更简便、更直接的能力。</p>
<ol>
    <li>使用全组织共享的单一源代码库<br>
        共享代码库，除了源码还可以存放学习经验和知识的工件：</li>
</ol>
<ul>
    <li>程序库、基础设施和环境（Chef的配方文件、Puppet类文件等）的配置标准</li>
    <li>部署工具</li>
    <li>测试标准和工具，包括安全方面</li>
    <li>部署流水线工具</li>
    <li>监测和分析工具</li>
    <li>教程和标准</li>
</ul>
<p>（我的理解单一源代码库不是只有一个源码库，而是所有人都能看到彼此的源码，而不是隔离开来，企业就好比Github中的组织，所有的源码都在该组织下，组织下的成员相互之间都能看到彼此的项目状况）</p>
<p>代码评审的指导原则：</p>
<ul>
    <li>每个人在将代码提交到主干之前，必须要有同行来审批他们的变更（代码、环境等）</li>
    <li>每个人都应该持续关注其他成员的提交活动，以便识别和审查出潜在的冲突</li>
    <li>定义哪些变更属于高风险的变更，从而决定是否需要请领域专家（例如数据库、身份验证模块等）来进行审查</li>
    <li>如果提交的变更尺寸太大了，以至于让人很难理解 — 换句话说，阅读了几遍代码还无法理解，或者需要提交者进行解释 — 那么这个变更就需要分解成多个较小的变更来提交（重构），使之一目了然</li>
</ul>
<p>代码评审的方式有：</p>
<ul>
    <li>结对编程：程序员结对在一起工作。</li>
    <li>“肩并肩”：一名程序员写了代码后，立刻另外一名进行阅读。</li>
    <li>电子邮件送审：代码提交后，系统自动发送邮件进行给相关人员邮寄代码</li>
    <li>工具辅助：编码者和审阅者都使用专门用于代码评审的工具（例如，Gerrit、GitHub的Pull Request），或者是源码仓库提供的工具（例如，GitHub、GitLab等）</li>
</ul>
<ol>
    <li>预留组织学习和改进的时间<br>
        丰田的改善闪电战，是找一个专门的集中的时间来处理解决特定问题，通常长达几天。DevOps道场是一个类似于丰田的改善闪电战的概念，通过设置专门的场所，汇聚专门的人才到一个地点针对特定问题进行集中解决，也类似于一些公司的“30天挑战”，或者“黑客马拉松”、“20%的创新时间”（我也创造了一个名词叫“巅峰编程”）之类的。这种方法可以促使团队快速成长，并且能够集中高效的解决问题。
    </li>
</ol>
<p>同时要预留改进系统的时间，以免欠下技术债，偿还起来是十分吓人的。创建论坛和知识库，让大家积极分享知识。同时让领域内的大咖定期授课，增加大家的知识。</p>
<h3>第六部分 集成信息安全、变更管理和合规性的技术实践</h3>
<p>要提高安全性，而且还要创建更易于审计、能证明控制有效性的流程，以遵从监管义务和合同义务。相关的举措如下：</p>
<ul>
    <li>使安全成为每个人工作的一部分</li>
    <li>将预防性的控制代码集成到共享代码库中</li>
    <li>将安全性与部署流水线集成</li>
    <li>将安全性与监控集成，从而更好地检测和恢复</li>
    <li>保护部署流水线</li>
    <li>将部署活动与变更审批流程集成</li>
    <li>减少对职责分离的依赖</li>
</ul>
<ol>
    <li>将信息安全融入每个人的日常工作<br>
        将安全集成到开发迭代中，尽早的和安全团队协作，而不是等到开发完成再集中处理安全。<br>
        将安全集成到缺陷跟踪和时候分析会议中。<br>
        将预防性安全控制集成到共享源代码库及共享服务中。<br>
        将安全集成到部署流水线中。</li>
</ol>
<p>我们的终极目的是为所有现代应用程序或环境提供所需的安全类库或服务，例如启用用户身份验证、授权、密码管理、数据加密等。此外，也可以为开发和运维团队应用程序栈中用到的组件提供安全方面的有效配置，例如用于日志记录、身份验证和加密。还可能包括以下相关内容：
</p>
<ul>
    <li>代码库及推荐的配置[例如，2FA、bcrypt密码散列、日志记录]</li>
    <li>使用Vault、sneaker、Keywhiz、credstash、Trousseau、Red October等工具进行密钥、密码管理（例如连接设置，加密密钥）</li>
    <li>操作系统软件包和构建（例如，用于时间同步的NTP，正确配置的安全版本的OpenSSL，用于文件完整性监视的OSSEC或Tripwire，用于确保将关键安全性日志都记录到集中式ELK系统里的syslog日志配置）
    </li>
</ul>
<ol>
    <li>保证应用程序的安全性<br>
        这需要QA在测试时不仅仅是要验证程序的正确性（也叫快了路径Happy path），另外一方面，也需要关注出错的情况（不愉快路径Sas path），甚至是一些与安全相关的情况（坏路径，Bad path）。</li>
</ol>
<p>除了上述测试以外，在部署流水线应该持续运行以下部分的测试：<br>
    * 静态分析：非运行时环境中执行的测试，期望在部署流水线中进行。通常静态分析工具可以达到这样的效果，包括Brakeman、Code Climate和搜索禁止代码功能（例如exec()）。（findbug）<br>
    * 动态分析：与静态分析相反，动态分析是一系列程序运行时的测试组成。动态测试监视诸如系统内存、功能行为、响应时间和系统整体性能等项目。此类工具包括Arachni和OWASP
    ZAP（Zed攻击代理）。还有一些渗透测试，例如Nmap和Metasploit等工具。<br>
    *
    依赖组件扫描：这是另外一种静态测试，通常是构建时在部署流水线中执行。它会清点二进制文件和可执行文件依赖的所有包和库，并确保这些依赖组件没有漏洞或者恶意二进制文件（想想前段时间出现的npm中某个包引起的大面积安全事件）。<br>
    * 源代码完整性和代码签名：所有开发人员都应该有自己的PGP密钥，可以再注入keybase.io之类的系统中创建和管理。想版本控制系统中提交的一切都应该签名 -
    使用开放源码工具gpg和git直接配置。此外，CI构建的所有包都应该签名，并且将其散列值记录在集中式日志记录服务中，为审计所用。</p>
<ol>
    <li>建立安全遥测系统<br>
        在应用程序中还应该建立安全遥测系统，这样的例子包括：
        <ul>
            <li>成功和不成功的用户登录</li>
            <li>用户密码重置</li>
            <li>用户电子邮件地址重置</li>
            <li>用户信用卡更改</li>
        </ul>
    </li>
</ol>
<p>在环境中建立安全遥测系统<br>
    * 操作系统的变更（例如，生产环境中、构建基础设施中）<br>
    * 安全组的变更<br>
    * 配置的变更（例如，OSSEC、Puppet、Chef、Tripwire）<br>
    * 云基础设施变更（例如，VPC、安全组、用户和权限）<br>
    * XSS尝试（即“跨站点脚本攻击”）<br>
    * SQLi尝试（即“SQL注入攻击”）<br>
    * Web服务器错误（例如，4xx和5xx错误）</p>
<ol>
    <li>保护部署流水线
        <ul>
            <li>加固持续构建和集成服务器</li>
            <li>审查任何提交到版本控制系统的变更</li>
            <li>检查包含可疑API调用的测试代码</li>
            <li>确保每个CI流程都运行在自己的隔离容器或虚拟机里</li>
            <li>确保CI系统使用的版本控制凭据是只读的</li>
        </ul>
    </li>
</ol>
<p>将安全和合规性集成到变更标准流程中<br>
    * 标准变更：遵循既定批准流程的低风险变更，但也可以是预批准的。这种类型的变更包括应用程序、网站内容、以及有已知影响的应用或操作系统补丁。<br>
    * 常规变更：风险更高、需要权威机构评审或批准的变更。<br>
    * 紧急变更：在紧急情况下必须立即投入生产环境的变更（例如，紧急安全补丁、恢复服务），属于潜在的高风险变更。</p>
<ol>
    <li>
        <p>减少对职责分离的依赖<br>
            以前的模式就是开发就是变更代码，运维变更部署到生产环境。而DevOps则是减少对职责分离的依赖，可以采用结对编程等方式使得开发和运维共同负责，共同保证。</p>
    </li>
    <li>
        <p>确保为审计人员和合规人员留存文档和证据</p>
    </li>
</ol>
<h2>感悟</h2>
<h3>如何才是有价值的交付？</h3>
<ul>
    <li>首先是要快速，互联网高效社会，speed wins，速度是第一价值。</li>
    <li>然后是保持小而简洁，大而复杂的东西，客户使用起来也会复杂。</li>
    <li>接着是基本完整性，麻雀虽小五脏俱全，即便是一个小功能，也要注重流程的完整性，又如传统的生产，哪怕一个螺丝刀，也会有说明书，他具备了一个完整产品所需的全部内容。</li>
    <li>最后是稳定性，不够稳定的系统必然是灾难重重的，极大的阻碍了用户的体验。</li>
</ul>
<h3>什么样的工作粒度是最好的？</h3>
<p>我认为最好的工作粒度是一个业务流程成为一个工作粒度。我们拿“用户注册”这个业务来说明，乍看之下，这好像就是一个业务流，“用户在网站首页点击注册按钮，进入注册页，输入注册信息，点击注册按钮，完成注册”。实则不然，因为用户注册流程还涉及到了其他的业务流程，例如“验证邮箱”，在用户注册的过程中，需要系统发送验证码到用户的邮箱。这就是另外一个业务流，“用户注册”中可能还包含了“激活用户”这个业务流，用户输入注册验证码，完成激活。这又是一个业务流。我们可以看到这个“用户注册”居然还成了一个特性群了。从系统层面来看，可能还有重构合并几个业务流成为一个系统业务流的需求。
</p>
<p>所以，总的来说，不可再拆分为其他业务流的这个业务流，就是最佳的工作粒度。这个粒度有简单的，也有难的，这就是要给每个业务流进行评分了。在敏捷开发中是有打分环节的，我们可以粗暴的定义几个分段，这样可以加快判别速度，只要达成了团队共识，甚至无需专门开打分会，每个团队成员皆可自行打分。<br>
    * 1分，最简单，只涉及少量的程序开发或者配置变动，只对自身有影响。例如只是将重构了类或者参数一些名字或者移动了位置等等。<br>
    * 2分，较简单，涉及部分程序开发或者配置变动，对自身和外部模块有影响，例如API的改动，增加了输入参数。这种改动由于涉及到了对外系统，所以必须改动测试用例。<br>
    * 3分，一般，涉及程序开发或者对外资源的使用，对自身和外部模块有影响。例如常规的业务的CRUD开发。<br>
    * 4分，较难，涉及程序开发、运用了简单算法或者对外资源的使用，对自身或者外部模块有影响。例如写了一个相似度算法来解决查询匹配业务流。<br>
    * 5分，很难，涉及程序开发、运用了复杂算法或者对外资源的使用，对自身或者外部模块有影响。例如根据公司需求写出了大数据算法。</p>
<p>所有的业务流开发除了业务开发以外，都必须配备单元测试。没有单元测试的，将会被扣除最多20%的分数。</p>
<p>这个粒度必须是从产品、开发到测试都认可的统一的粒度，每个业务流完成之后皆可以独立打包进入测试服务器，完成测试后，即可立即上限。</p>
<h3>反馈的意义</h3>
<p>反馈的精髓在于及时发现问题，找到问题几乎就找到了答案，及时找到，及时就能反馈。没有问题的反馈价值不大。</p>
<h3>对于人才培养</h3>
<p>DevOps里面提到了I型、T型和E型，看起来I型是基础，T型是很好，E型是非常好，DevOps的价值主张就是要需要每个人都是E型（市场型组织而非职能型组织），所以作为践行DevOps的管理者来说，需要将每个员工都培训成为E型人才。
</p>
<h3>DevOps就是博采众家之长</h3>
<p>突然才发现DevOps为什么要先说“所有的公司都是科技型公司，连传统的银行业也是”了，因为只要是科技型公司，DevOps就一定适用。DevOps就是博采众家之长，例如敏捷、丰田方法、持续交互。</p>
<h3>金丝雀发布</h3>
<p>是指发布到正式环境，但是只开放给极少量的用户使用，从而保证应用正常。我认为做这个事儿的前提得有几个，<br>
    * 更新必须是增量式（包括数据库结构）<br>
    * 必须有完善的生产环境通道路由保证</p>
<h3>Facebook的发布</h3>
<p>facebook发布管理者点击红色按钮启动发布，通过hiphop编译器把PHP转换成C++代码，再进一步编译为一个1.5GB的可执行文件，然后通过P2P模式复制到各个服务器上，完成更新部署。</p>
<h3>数据结构更新</h3>
<p>可以采用数据库迁移的方式来完成数据结构的更新，并结合蓝绿发布模式等方式来实现新旧系统的平滑过渡。</p>
<h3>PHP的冒烟测试</h3>
<p>可以采用cURL来执行PHPUnit测试用例。</p>
<h3>A/B测试</h3>
<p>书中说的在测试中、发布中和规划中都应该考虑到A/B测试，我认为非常重要，特别是在规划中，这样一来，就迫使开发人员在底层架构中必须设计出能够支撑A/B测试能力的底层逻辑，同时发布的工程也可以是A/B两个版本，分别调用A/B两个特性API。
</p>
<p>虽然A/B测试有可能的结果是废除A或者B，但是被废除的形式并不是没有价值，它的价值就是告诉了我们哪一个才是最佳的，而最佳的那一个的价值足以弥补A/B测试多出那一点设计。</p>
<p>即便A/B测试如此还用，但是我目前的理解还是觉得，创业初期，小团队规模，还是不要采用A/B测试，除非成本较小。先求成品，再求优化，然后多变。</p>